/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package boilerplates;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

/**
 *
 * @author daniel
 */
public class Boilerplate {
    private int IdDB;
    public int Id;
    public String description;
    public String genericModel;
    public HashSet<String> tags;

    public Boilerplate(int ID, String description, String genericModel) throws Exception {
        this.Id = ID;
        this.description = description;
        this.genericModel = genericModel;
        if(checkConsistency())
        {
            this.tags=getTags(this.description);
        }
        else{
            throw new Exception("Consistency failed to Boilerplate "+this.Id);
        }
    }

    public Boilerplate(int IDDB, int ID, String description, String genericModel) throws Exception {
        this.IdDB = IDDB;
        this.Id = ID;
        this.description = description;
        this.genericModel = genericModel;
        if(checkConsistency())
        {
            this.tags=getTags(this.description);
        }
        else{
            throw new Exception("Consistency failed to Boilerplate "+this.Id);
        }
    }

    /**
     * Creates a boilerplate from a custom file.
     * File must be organized in the following format:
     * --BEGINID--
     * Boilerplate_id (integer)
     * --ENDID--
     * --BEGINDESC--
     * Boilerplate Description.
     * --ENDDESC--
     * --BEGINMODEL--
     * Boilerplate Generic Model.
     * --ENDMODEL--
     * EX:
     * --BEGINID--
     * 01
     * --ENDID--
     * --BEGINDESC--
     * The <System> shall be able to <action>
     * --ENDDESC--
     * --BEGINMODEL--
     * sig <System> {
     * }
     * 
     * pred <Action>[s,s':<System>]{
     * }
     * --ENDMODEL--
     * 
     * @param fileName
     */
    public Boilerplate(String fileName) throws FileNotFoundException, IOException, Exception{
        BufferedReader bout = new BufferedReader(new FileReader(fileName));
        String line ="";
        this.description = new String("");
        this.genericModel = new String("");
        while ((line = bout.readLine()) != null)
        {
            if(line.indexOf("--BEGINID--")!=-1)
            {
                line = bout.readLine();
                this.Id = Integer.parseInt(line);
            }
            if(line.indexOf("--BEGINDESC--")!=-1)
            {
                line = bout.readLine();
                while(line.indexOf("--ENDDESC--")==-1)
                {
                    this.description += line+"\n";
                    line = bout.readLine();
                    
                }
            }
            if(line.indexOf("--BEGINMODEL--")!=-1)
            {
                line = bout.readLine();
                while(line.indexOf("--ENDMODEL--")==-1)
                {
                    this.genericModel += line+"\n";
                    line = bout.readLine();
                }
            }
        }

       
        
        if(checkConsistency())
        {
            this.tags=getTags(this.description);
        }
        else{
            throw new Exception("Consistency failed to Boilerplate "+this.Id);
        }
    }

    /**
     * Returns a list of tags from the string.
     * @param str with a list of tags in form <Tag1>,<Tag2>, etc
     * @return ArrayList of tags.
     */
    private HashSet<String> getTags(String str)
    {
        HashSet<String> list = new HashSet<String>();
        int len= str.length();
        for(int i=0; i<len; i++)
        {
            if(str.charAt(i)=='<')
            {
                
                String tmp1 = str.substring(i+1, len);
                int posfinal = tmp1.indexOf(">");
                String tmp2 = tmp1.substring(0,posfinal);
                list.add(tmp2);
                i++;
            }
        }
        return list;
        
    }

    /*/**
     * Checks if description contains tags which doesn't appear in generic model.
     * @return
     
    private boolean checkDescConsistency()
    {
        ArrayList<String> tagsDesc = getTags(this.description);
        ArrayList<String> tagsModel = getTags(this.genericModel);
        if(!tagsDesc.equals(tagsModel)) return false;
        return true;
    }

    /**
     * Checks if generic model contains tags which doesn't appear in description.
     * @return
     
    private boolean checkModelConsistency()
    {
        return true;
    }
    /**
     * Checks if generic model contains tags which doesn't appear in description, and vice-versa.
     * @return
     */
    private boolean checkConsistency()
    {
        HashSet<String> tagsDesc = getTags(this.description);
        HashSet<String> tagsModel = getTags(this.genericModel);
        
        if(!tagsDesc.equals(tagsModel)) return false;
        return true;
    }

    /**
     * Receives an hashmap containing pairs tag,value and returns the instanciated model.
     * @param instances
     * @return
     * @throws Exception
     */
    public String getInstanciatedModel(HashMap<String,String> instances) throws Exception
    {
        String tmp = new String(this.genericModel);
        if(!instances.keySet().equals(this.tags)){
            throw new Exception("Tags for instanciation doesn't match boilerplate "+this.Id+" tags.");
        }
        for(String s : this.tags)
        {
           tmp = tmp.replace("<"+s+">", instances.get(s));
        }
        
        return tmp;
    }

    public int getId() {
        return Id;
    }

    public void setId(int Id) {
        this.Id = Id;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getGenericModel() {
        return genericModel;
    }

    public void setGenericModel(String genericModel) {
        this.genericModel = genericModel;
    }

    public int getIdDB() {
        return IdDB;
    }

    public void setIdDB(int IdDB) {
        this.IdDB = IdDB;
    }

    /**
     * Receives a boilerplate instanciated with values and extract pairs attribute,value.
     * Ex:
     *
     * If boilerplate is: The <System> shall be able to <action>
     * and instance is: The Air Condition shall be able to blow fresh air.
     * returns (System, AirCondition),(Action, blowfreshair)
     * @param instance
     * @return
     */
    /*public HashMap<String,String> extractValues(String instance)
    {
        HashMap<String, String> values = new HashMap<String,String>();
        for(String s : this.tags)
        {
            String value = extractValue(s,instance);
            values.put(s, value);
        }
        return values;

    }*/

}
